#pragma once

#include "../stdafx.h"
#include "collada\\Index.h"
#include "collada\\Weight.h"
#include <vector>

enum VERTEXTYPE
{
	VT_POS=0,
	VT_POSNORM,
	VT_POSNORMUV,
	VT_POSNORMUVTANG,//=4,//tangent+binormal --> trick in "iVtype++" code in binormal case in ColladaLoader.h
	VT_POSNORMUVTANG_SKIN,
};

const char* VERTEXTYPENAME[]; 

const D3D11_INPUT_ELEMENT_DESC VertexNormUVTang_Morph_Layout[] =
{
	//1st Stream: Base Mesh
	{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "BINORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 44, D3D11_INPUT_PER_VERTEX_DATA, 0 },

	//2nd Stream:
	{"POSITION1", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "NORMAL1",   0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },

	//3rd Stream:
	{"POSITION2", 0, DXGI_FORMAT_R32G32B32_FLOAT, 2,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "NORMAL2",   0, DXGI_FORMAT_R32G32B32_FLOAT, 2, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },

	//4th Stream:
	{"POSITION3", 0, DXGI_FORMAT_R32G32B32_FLOAT, 3,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "NORMAL3",   0, DXGI_FORMAT_R32G32B32_FLOAT, 3, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },

	//5th Stream:
	{"POSITION4", 0, DXGI_FORMAT_R32G32B32_FLOAT, 4,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "NORMAL4",   0, DXGI_FORMAT_R32G32B32_FLOAT, 4, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },

};

class Vertex
{
public:
	//Components of a Vertex
	D3DXVECTOR3 Position;
	static const D3D11_INPUT_ELEMENT_DESC layout[1];
	static const D3DVERTEXELEMENT9 VERTEX_DECL[];
	static const unsigned int STRIDE_SIZE;
	static enum VERTEXTYPE VType;
	Vertex()
	{
		Position = D3DXVECTOR3(0,0,0);		
	}
	~Vertex(){}
	//Constructor
	Vertex(const D3DXVECTOR3& Position)
	{
		this->Position = Position;
	}

	Vertex(D3DXVECTOR3* pos, D3DXVECTOR3* norm = NULL, D3DXVECTOR2* uv = NULL, D3DXVECTOR3* tang = NULL, D3DXVECTOR3* binorm = NULL)
	{
		this->Position = *pos;
	}

	static void AddIntoArray(std::vector<Vertex>& arr, D3DXVECTOR3* pos, D3DXVECTOR3* norm = NULL, D3DXVECTOR2* uv = NULL, D3DXVECTOR3* tang = NULL, D3DXVECTOR3* binorm = NULL)
	{
		arr.push_back(Vertex(*pos));
	}
};


class VertexNorm
{
public:
	//Components of a Vertex
	D3DXVECTOR3 Position;
	D3DXVECTOR3 Normal;
	static const D3D11_INPUT_ELEMENT_DESC layout[2];
	static const D3DVERTEXELEMENT9 VERTEX_DECL[];
	static const unsigned int STRIDE_SIZE;
	static enum VERTEXTYPE VType;
	VertexNorm()
	{
		Position = D3DXVECTOR3(0,0,0);
		Normal = D3DXVECTOR3(0,0,0);		
	}
	~VertexNorm(){}
	//Constructor
	VertexNorm(const D3DXVECTOR3& Position, const D3DXVECTOR3& Normal)
	{
		this->Position = Position;
		this->Normal = Normal;
	}

	VertexNorm(D3DXVECTOR3* pos, D3DXVECTOR3* norm, D3DXVECTOR2* uv = NULL, D3DXVECTOR3* tang = NULL, D3DXVECTOR3* binorm = NULL)
	{
		this->Position = *pos;
		this->Normal = *norm;
	}
	static void AddIntoArray(std::vector<VertexNorm>& arr, D3DXVECTOR3* pos, D3DXVECTOR3* norm, D3DXVECTOR2* uv = NULL, D3DXVECTOR3* tang = NULL, D3DXVECTOR3* binorm = NULL)
	{
		arr.push_back(VertexNorm(*pos,*norm));
	}
};

class VertexNormUV
{
public:
	//Components of a Vertex
	D3DXVECTOR3 Position;
	D3DXVECTOR3 Normal;	
	D3DXVECTOR2 UV;
	static const D3D11_INPUT_ELEMENT_DESC layout[3];
	static const D3DVERTEXELEMENT9 VERTEX_DECL[];
	static const unsigned int STRIDE_SIZE;
	static enum VERTEXTYPE VType;
	
	VertexNormUV()
	{
		Position = D3DXVECTOR3(0,0,0);
		Normal = D3DXVECTOR3(0,0,0);	
		UV = D3DXVECTOR2(0,0);
	}
	~VertexNormUV(){}

	//Constructor
	VertexNormUV(const D3DXVECTOR3& Position, const D3DXVECTOR3& Normal, const D3DXVECTOR2& UV)
	{
		this->Position = Position;
		this->Normal = Normal;
		this->UV = UV;
	}
	VertexNormUV(D3DXVECTOR3* pos, D3DXVECTOR3* norm, D3DXVECTOR2* uv, D3DXVECTOR3* tang = NULL, D3DXVECTOR3* binorm = NULL)
	{
		this->Position = *pos;
		this->Normal = *norm;
		this->UV = *uv;
	}
	static void AddIntoArray(std::vector<VertexNormUV>& arr, D3DXVECTOR3* pos, D3DXVECTOR3* norm, D3DXVECTOR2* uv, D3DXVECTOR3* tang = NULL, D3DXVECTOR3* binorm = NULL)
	{
		arr.push_back(VertexNormUV(*pos,*norm,*uv));
	}
};


class VertexNormUVTang
{
public:
	//Components of a Vertex
	D3DXVECTOR3 Position;
	D3DXVECTOR3 Normal;	
	D3DXVECTOR2 UV;
	D3DXVECTOR3 Tangent;
	D3DXVECTOR3 BiNormal;
	static const D3D11_INPUT_ELEMENT_DESC layout[5];
	static const D3DVERTEXELEMENT9 VERTEX_DECL[];
	static const unsigned int STRIDE_SIZE;
	static enum VERTEXTYPE VType;
	
	VertexNormUVTang()
	{
		Position = D3DXVECTOR3(0,0,0);
		Normal = D3DXVECTOR3(0,0,0);	
		UV = D3DXVECTOR2(0,0);
		Tangent = D3DXVECTOR3(0,0,0);
		BiNormal = D3DXVECTOR3(0,0,0);		
	}
	~VertexNormUVTang(){}
	//Constructor
	VertexNormUVTang(const D3DXVECTOR3& Position, const D3DXVECTOR3& Normal, const D3DXVECTOR2& UV, const D3DXVECTOR3& Tangent, const D3DXVECTOR3& BiNormal)
	{
		this->Position = Position;
		this->Normal = Normal;
		this->UV = UV;
		this->Tangent = Tangent;
		this->BiNormal = BiNormal;		
	}
	VertexNormUVTang(D3DXVECTOR3* pos, D3DXVECTOR3* norm, D3DXVECTOR2* uv, D3DXVECTOR3* tang, D3DXVECTOR3* binorm)
	{
		this->Position = *pos;
		this->Normal = *norm;
		this->UV = *uv;
		this->Tangent = *tang;
		this->BiNormal = *binorm;
	}
	static void AddIntoArray(std::vector<VertexNormUVTang>& arr, D3DXVECTOR3* pos, D3DXVECTOR3* norm, D3DXVECTOR2* uv, D3DXVECTOR3* tang, D3DXVECTOR3* binorm)
	{
		arr.push_back(VertexNormUVTang(*pos,*norm,*uv,*tang,*binorm));
	}
};


class VertexNormUVTangSkinned
{
public:
	D3DXVECTOR3 Position;
	D3DXVECTOR3 Normal;	
	D3DXVECTOR2 UV;
	D3DXVECTOR3 Tangent;
	D3DXVECTOR3 BiNormal;
	SkinIndex BoneIndices;
	SkinWeight Weights;
	static const D3D11_INPUT_ELEMENT_DESC layout[7];
	static const unsigned int STRIDE_SIZE;
	static enum VERTEXTYPE VType;
	//Constructor
	VertexNormUVTangSkinned()
	{
		Position = D3DXVECTOR3(0,0,0);
		Normal = D3DXVECTOR3(0,0,0);	
		UV = D3DXVECTOR2(0,0);
		Tangent = D3DXVECTOR3(0,0,0);
		BiNormal = D3DXVECTOR3(0,0,0);	
	}
	VertexNormUVTangSkinned(const D3DXVECTOR3& Position, const D3DXVECTOR3& Normal, const D3DXVECTOR2& UV, const D3DXVECTOR3& Tangent, const D3DXVECTOR3& BiNormal, 
		const SkinIndex& BoneIndices, const SkinWeight& Weights)
	{
		this->Position = Position;
		this->Normal = Normal;
		this->UV = UV;
		this->Tangent = Tangent;
		this->BiNormal = BiNormal;	
		this->BoneIndices = BoneIndices;
		this->Weights = Weights;		
	}
};

